package com.seven.smartsnmp.discover.service;

import com.seven.smartsnmp.config.DiscoverConfig;
import com.seven.smartsnmp.discover.DeviceInfo;
import com.seven.smartsnmp.discover.DeviceTypeInfo;
import com.seven.smartsnmp.mib.MibMacIP;
import com.seven.smartsnmp.snmp.SNMPTarget;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

public class SearchDeviceByIPRoaming {

    private ConcurrentLinkedQueue<DeviceInfo> allRoamedDeviceList = new ConcurrentLinkedQueue();

    public SearchDeviceByIPRoaming() {
    }

    /**
     * 判断是否是重复设备
     *
     * @param ip
     * @param mac
     * @return
     */
    private boolean isDeviceExist(String ip, String mac) {
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.setDeviceIP(ip);
        deviceInfo.setDeviceMAC(mac);
        return allRoamedDeviceList.contains(deviceInfo);
    }

    /**
     * @param ipQueue
     * @param snmpTargets
     * @param isPing
     * @param depth
     * @param maxNum
     * @return
     */
    public ConcurrentLinkedQueue<DeviceInfo> searchDeviceByIPRoaming(ConcurrentLinkedQueue<String> ipQueue, List<SNMPTarget> snmpTargets, boolean isPing, int depth, int maxNum) {
        if (depth >= 8) {
            depth = 8;
        }
        if (maxNum >= 2048) {
            maxNum = 2048;
        }
        ConcurrentLinkedQueue<DeviceInfo> devQueue = (new SearchNodeService()).searchDeviceByNetList(ipQueue, snmpTargets, isPing);
        this.allRoamedDeviceList.addAll(devQueue);
        for (int i = 1; i <= depth && this.allRoamedDeviceList.size() < maxNum; i++) {
            devQueue = this.getOtherDeviceByRouter(devQueue, snmpTargets, isPing);
            this.allRoamedDeviceList.addAll(devQueue);
        }
        return this.allRoamedDeviceList;
    }

    /**
     * @param ip
     * @param snmpTargets
     * @param isPing
     * @param depth
     * @param maxNum
     * @return
     */
    public ConcurrentLinkedQueue<DeviceInfo> searchDeviceByIPRoaming(String ip, List<SNMPTarget> snmpTargets, boolean isPing, int depth, int maxNum) {
        if (depth >= 8) {
            depth = 8;
        }
        if (maxNum >= 2048) {
            maxNum = 2048;
        }
        ConcurrentLinkedQueue ipQueue = new ConcurrentLinkedQueue();
        ipQueue.add(ip);
        ConcurrentLinkedQueue deviceInfos = (new SearchNodeService()).searchDeviceByIPList(ipQueue, snmpTargets, isPing);
        this.allRoamedDeviceList.addAll(deviceInfos);
        for (int i = 1; i <= depth; i++) {
            deviceInfos = this.getOtherDeviceByRouter(deviceInfos, snmpTargets, isPing);
            this.allRoamedDeviceList.addAll(deviceInfos);
            if (this.allRoamedDeviceList.size() >= maxNum) {
                break;
            }
        }
        return this.allRoamedDeviceList;
    }


    /**
     * @param deviceInfos
     * @param snmpTargets
     * @param isUsePing
     * @return
     */
    private ConcurrentLinkedQueue<DeviceInfo> getOtherDeviceByRouter(ConcurrentLinkedQueue<DeviceInfo> deviceInfos, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        ConcurrentLinkedQueue<DeviceInfo> devQueue = new ConcurrentLinkedQueue<>();
        ConcurrentLinkedQueue<String> ipQueue = new ConcurrentLinkedQueue<>();
        Iterator<DeviceInfo> it = deviceInfos.iterator();
        while (it.hasNext()) {
            DeviceInfo deviceInfo = it.next();
            if (!DiscoverConfig.isIPRoamingAll &&
                    !deviceInfo.getDeviceType().equalsLogicType(DeviceTypeInfo.RouterType) &&
                    !deviceInfo.getDeviceType().equalsLogicType(DeviceTypeInfo.RouterSwitchType)) {
                System.out.println("设备不是网络设备-----");
            } else {
                //arp表
                List macIPList = deviceInfo.getMibMacIPList();
                Iterator iterator = macIPList.iterator();
                while (iterator.hasNext()) {
                    MibMacIP mibMacIP = (MibMacIP) iterator.next();
                    if (mibMacIP.getIpNetToMediaType() != 2) {
                        String ip = mibMacIP.getIpNetToMediaNetAddress();
                        String mac = mibMacIP.getIpNetToMediaPhysAddress();
                        if (!this.isDeviceExist(ip, mac) && !ipQueue.contains(ip)) {
                            ipQueue.add(ip);
                        }
                    }
                }
                ConcurrentLinkedQueue<DeviceInfo> tempQueue = (new SearchNodeService()).searchDeviceByIPList(ipQueue, snmpTargets, isUsePing);
                Iterator infoIterator = tempQueue.iterator();
                while (iterator.hasNext()) {
                    DeviceInfo dev = (DeviceInfo) infoIterator.next();
                    if (!this.allRoamedDeviceList.contains(dev)) {
                        devQueue.add(dev);
                    }
                }
            }
        }
        return devQueue;
    }

    /**
     * 获取路由表
     *
     * @param deviceInfos
     * @param snmpTargets
     * @param isUsePing
     * @return
     */
    private ConcurrentLinkedQueue<DeviceInfo> getDeviceByRouter(ConcurrentLinkedQueue<DeviceInfo> deviceInfos, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        ConcurrentLinkedQueue<DeviceInfo> devQueue = new ConcurrentLinkedQueue<>();
        ConcurrentLinkedQueue<String> ipQueue = new ConcurrentLinkedQueue<>();
        Iterator<DeviceInfo> it = deviceInfos.iterator();
        while (it.hasNext()) {
            DeviceInfo deviceInfo = it.next();
            if (!DiscoverConfig.isIPRoamingAll &&
                    !deviceInfo.getDeviceType().equalsLogicType(DeviceTypeInfo.RouterType) &&
                    !deviceInfo.getDeviceType().equalsLogicType(DeviceTypeInfo.RouterSwitchType)) {
                System.out.println("设备不是网络设备-----");
            } else {
                //arp表
                List macIPList = deviceInfo.getMibMacIPList();
                Iterator iterator = macIPList.iterator();
                while (iterator.hasNext()) {
                    MibMacIP mibMacIP = (MibMacIP) iterator.next();
                    if (mibMacIP.getIpNetToMediaType() != 2) {
                        String ip = mibMacIP.getIpNetToMediaNetAddress();
                        String mac = mibMacIP.getIpNetToMediaPhysAddress();
                        if (!this.isDeviceExist(ip, mac) && !ipQueue.contains(ip)) {
                            ipQueue.add(ip);
                        }
                    }
                }
                ConcurrentLinkedQueue<DeviceInfo> tempQueue = (new SearchNodeService()).searchDeviceByIPList(ipQueue, snmpTargets, isUsePing);
                Iterator infoIterator = tempQueue.iterator();
                while (iterator.hasNext()) {
                    DeviceInfo dev = (DeviceInfo) infoIterator.next();
                    if (!this.allRoamedDeviceList.contains(dev)) {
                        devQueue.add(dev);
                    }
                }
            }
        }
        return devQueue;
    }

}
